/**
 * create by zhangpu
 * date:2015年4月12日
 */
package com.acooly.module.openapi.client.api.notify;

import com.acooly.core.utils.Exceptions;
import com.acooly.module.openapi.client.api.ApiServiceClient;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.message.ApiMessage;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Map;

/**
 * 异步通知 分发器 默认实现
 *
 * @author zhangpu
 */
public abstract class AbstractSpringNotifyHandlerDispatcher
        implements NotifyHandlerDispatcher, ApplicationContextAware, InitializingBean, NotifyHandlerFactory {

    private static Logger logger = LoggerFactory.getLogger(AbstractSpringNotifyHandlerDispatcher.class);
    private Map<String, NotifyHandler> handlers = Maps.newHashMap();

    private NotifyHandler defaultNotifyHandler = new DefaultNotifyHandler();

    private ApplicationContext applicationContext;


    @Override
    public void dispatch(String notifyUrl, Map<String, String> notifyData) {
        logger.info("异步通知 入参:url:{},data:{}", notifyUrl, notifyData);
        try {
            beforeDispatch(notifyUrl, notifyData);
            String serviceKey = getServiceKey(notifyUrl, notifyData);
            ApiMessage notify = getApiServiceClient().notice(notifyData, serviceKey);
            doDispatch(serviceKey, notify);
            logger.info("异步通知 出参:处理成功");
        } catch (Exception e) {
            logger.error("异步通知 出参:处理失败:{}", e.getMessage());
            throw new ApiClientException("异步通知 出参:处理失败: " + e.getMessage());
        } finally {
            afterDispatch(notifyUrl, notifyData);
        }
    }

    @Override
    public NotifyHandler getNotifyHandler(String serviceKey) {
        return handlers.get(serviceKey);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, NotifyHandler> handlerBeanMaps = applicationContext.getBeansOfType(NotifyHandler.class);
        for (NotifyHandler handler : handlerBeanMaps.values()) {
            handlers.put(handler.serviceKey(), handler);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    protected abstract String getServiceKey(String notifyUrl, Map<String, String> notifyData);

    protected abstract ApiServiceClient getApiServiceClient();

    protected void doDispatch(String serviceKey, ApiMessage notify) {
        try {
            NotifyHandler handler = getNotifyHandler(serviceKey);
            if (handler == null) {
                handler = defaultNotifyHandler;
                logger.info("没有找到对应的异步通知处理器，请检查配置或环境,采用默认的处理器处理。");
            }
            handler.handleNotify(notify);
        } catch (Exception e) {
            throw Exceptions.unchecked(e);
        }
    }


    protected void beforeDispatch(String notifyUrl, Map<String, String> notifyData) {

    }

    protected void afterDispatch(String notifyUrl, Map<String, String> notifyData) {

    }

}
